/********************************************
* Copyrigt (C) rumi
* Module: bsp_iic.c
*********************************************/
#include "bsp_iic.h"
static const char *TAG = "bsp_iic.c";

i2c_master_bus_config_t i2c_bus_config = {
        .clk_source = I2C_CLK_SRC_DEFAULT,
        .i2c_port = PORT_NUMBER,
        .scl_io_num = SCL_IO_PIN,
        .sda_io_num = SDA_IO_PIN,
        .glitch_ignore_cnt = 7,
    };

i2c_master_bus_handle_t bus_handle;
i2c_subdevice_handle_t  my_subdevice_handle;

i2c_subdevice_config_t subdevice_config = {
    .subdevice_device.scl_speed_hz = 200000,
    .subdevice_device.device_address = 0xD0,
    .addr_wordlen = 2,
    .write_time_ms = 10,
};

esp_err_t i2c_subdevice_init(i2c_master_bus_handle_t bus_handle, const i2c_subdevice_config_t *subdevice_config, i2c_subdevice_handle_t *subdevice_handle)
{
    esp_err_t ret = ESP_OK;
    i2c_subdevice_handle_t out_handle;
    out_handle = (i2c_subdevice_handle_t)calloc(1, sizeof(i2c_subdevice_handle_t));
    ESP_GOTO_ON_FALSE(out_handle, ESP_ERR_NO_MEM, err, TAG, "no memory for i2c subdevice device");

    i2c_device_config_t i2c_dev_conf = {
        .scl_speed_hz = subdevice_config->subdevice_device.scl_speed_hz,
        .device_address = subdevice_config->subdevice_device.device_address,
    };

    if (out_handle->i2c_dev == NULL) {
        ESP_GOTO_ON_ERROR(i2c_master_bus_add_device(bus_handle, &i2c_dev_conf, &out_handle->i2c_dev), err, TAG, "i2c new bus failed");
    }

    out_handle->buffer = (uint8_t*)calloc(1, subdevice_config->addr_wordlen + I2C_EEPROM_MAX_TRANS_UNIT);
    ESP_GOTO_ON_FALSE(out_handle->buffer, ESP_ERR_NO_MEM, err, TAG, "no memory for i2c eeprom device buffer");

    out_handle->addr_wordlen = subdevice_config->addr_wordlen;
    out_handle->write_time_ms = subdevice_config->write_time_ms;
    *subdevice_handle = out_handle;

    return ESP_OK;

err:
    if (out_handle && out_handle->i2c_dev) {
        i2c_master_bus_rm_device(out_handle->i2c_dev);
    }
    free(out_handle);
    return ret;
}

esp_err_t i2c_subdevice_read(i2c_subdevice_handle_t subdevice_handle, uint32_t address, uint8_t *data, uint32_t size)
{
    ESP_RETURN_ON_FALSE(subdevice_handle, ESP_ERR_NO_MEM, TAG, "no mem for buffer");
    for (int i = 0; i < subdevice_handle->addr_wordlen; i++) {
        subdevice_handle->buffer[i] = (address & (0xff << ((subdevice_handle->addr_wordlen - 1 - i) * 8))) >> ((subdevice_handle->addr_wordlen - 1 - i) * 8);
    }

    return i2c_master_transmit_receive(subdevice_handle->i2c_dev, subdevice_handle->buffer, subdevice_handle->addr_wordlen, data, size, -1);
}

esp_err_t i2c_subdevice_write(i2c_subdevice_handle_t subdevice_handle, uint32_t address, const uint8_t *data, uint32_t size)
{
    ESP_RETURN_ON_FALSE(subdevice_handle, ESP_ERR_NO_MEM, TAG, "no mem for buffer");
    for (int i = 0; i < subdevice_handle->addr_wordlen; i++) {
        subdevice_handle->buffer[i] = (address & (0xff << ((subdevice_handle->addr_wordlen - 1 - i) * 8))) >> ((subdevice_handle->addr_wordlen - 1 - i) * 8);
    }
    memcpy(subdevice_handle->buffer + subdevice_handle->addr_wordlen, data, size);

    return i2c_master_transmit(subdevice_handle->i2c_dev, subdevice_handle->buffer, subdevice_handle->addr_wordlen + size, -1);
}

void bsp_iic_init()
{
    ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &bus_handle));
    ESP_ERROR_CHECK(i2c_subdevice_init(bus_handle, &subdevice_config, &my_subdevice_handle));
}

/********************************************
 * End of file
*********************************************/